#ifndef PLCDATAPROCESS_H
#define PLCDATAPROCESS_H

#include <QObject>
#include "plcconnecter.h"
#include "../safeQueue/readerwriterqueue.h"

#define PLCDATAPROCESSER HIM::PlcDataProcess::getInstance()

namespace HIM{

typedef enum{
    SO_VD0_0 =    0x0000,
    SO_VD4_0 =    0x0020,
    SO_VD8_0 =    0x0040,
    SO_VD12_0 =   0x0060,
    SO_VD16_0 =   0x0080,
    SO_VD20_0 =   0x00A0,
    SO_VD24_0 =   0x00C0,
    SO_VD28_0 =   0x00E0,
    SO_VD32_0 =   0x0100,
    SO_VD36_0 =   0x0120,
    SO_VD40_0 =   0x0140,
    SO_VD44_0 =   0x0160,
    SO_VW48_0 =   0x0180,
    SO_V50_0 =    0x0190,
    SO_V50_1,
    SO_V50_2,
    SO_V50_3,
    SO_V50_4,
    SO_V50_5,
    SO_V50_6,
    SO_V50_7,
    SO_V50_8,
    SO_V50_9,
    SO_V50_10,
    SO_V50_11,
    SO_V50_12,
    SO_V50_13,
    SO_V50_14,
    SO_V50_15,
    SO_V52_0 =    0x01A0,
    SO_V52_1,
    SO_V52_2,
    SO_V52_3,
    SO_V52_4,
    SO_V52_5,
    SO_V52_6,
    SO_V52_7,
    SO_V52_8,
    SO_V52_9,
    SO_V52_10,
    SO_V52_11,
    SO_V52_12,
    SO_V52_13,
    SO_V52_14,
    SO_V52_15,
    SO_VD56_0 =   0x01C0,
    SO_VD60_0 =   0x01E0,
    SO_VD64_0 =   0x0200,
    SO_VD68_0 =   0x0220,
    SO_VD72_0 =   0x0240,
    SO_V76_0 =    0x0260,
    SO_V76_1,
    SO_V76_2,
    SO_V76_3,
    SO_V76_4,
    SO_V76_5,
    SO_V76_6,
    SO_V76_7,
    SO_V76_8,
    SO_V76_9,
    SO_VD80_0 = 0x0280 ,
    SO_VD84_0 = 0x02A0
} AddressIndex;

typedef enum{
    BIT,
    INT_16,
    FLOAT_32
}DataType;

typedef struct
{
    AddressIndex addressIndex;
    DataType dataType{BIT};
    bool bit{0};
    int16_t int16{0};
    float float32{0.};
}PLCTask;

class PlcDataProcess :public QObject
{
    Q_OBJECT
public:
    static PlcDataProcess& getInstance(){
        static PlcDataProcess instance;
        return instance;
    }    

    void setPlcData();

    int16_t GetPlcBitData(AddressIndex ind , uint16_t PlcReadData[100]);
    int16_t GetPlcWordData(AddressIndex ind , uint16_t PlcReadData[100]);
    float GetPlcFloatData(AddressIndex ind , uint16_t PlcReadData[100]);

    void addSetPlcBitDataTask(AddressIndex ind,bool data);
    void addSetPlcWordDataTask(AddressIndex ind,int16_t data);
    void addSetPlcFloatDataTask(AddressIndex ind,float data);

private:
    PlcDataProcess(){};
    PlcDataProcess(const PlcDataProcess&)=delete ;
    PlcDataProcess& operator=(const PlcDataProcess&)=delete ;

private:
    uint16_t* setDByteFromBit(AddressIndex ind , bool data);
    void setDDByteFromLong(long src, uint16_t* des);
    void swapDDByte(uint16_t* src, uint16_t* des);
    uint16_t getBitFromDByte(uint16_t* src,uint8_t loc);
    uint16_t getBitsFromDByte(uint16_t* src,uint8_t loc,uint8_t nb);
    int32_t getDataFromDDByte(uint16_t* src);
    int32_t getLongfromDDByte(uint16_t* src);

private:
    /********** Parameters relating to plc reading ************/
//    unsigned int plcReadLength{100};
//    unsigned int plcWriteLength{100};
    unsigned int read_starting_addr{0};

    uint16_t PlcSingleWriteData;

    moodycamel::ReaderWriterQueue<PLCTask> plcTaskList ;
};
}
#endif // PLCDATAPROCESS_H
